// 原型链继承
  // 优点
    // 写法方便
  // 缺点
    // 每继承一次都需要实例化一次父类，性能浪费
    // 子类实例化后进行的修改会被共享
    // 子类无法向父类的构造函数传参
  // function Animal() {
  //   this.colors = ['black', 'white']
  // }
  // Animal.prototype.getColor = function () {
  //   return this.colors
  // }
  // function Dog() {}
  // // 每次继承都需要重新实例化 浪费性能
  // Dog.prototype = new Animal()
  // let dog1 = new Dog()
  // dog1.colors.push('brown')
  // console.log('dog1.getColor', dog1.getColor())
  // let dog2 = new Dog()
  // console.log('dog2.getColor', dog2.getColor())

// 构造函数继承
  // 优点
    // 子类被实例化后参数不共享
    // 可以向父类的构造函数传参
  // function Animal(name) {
  //   this.name = name
  //   this.colors = ['black', 'white']
  //   this.getColors = function () {
  //     return this.colors
  //   }
  //   this.getName = function () {
  //     return this.name
  //   }
  // }
  // function Dog(name) {
  //   Animal.call(this, name)
  // }
  // Dog.prototype = new Animal()
  // let dog1 = new Dog('dog1')
  // let dog2 = new Dog('dog2')
  // dog1.colors.push('brown')
  // console.log('dog1\'s name is ', dog1.getName())
  // console.log('dog2\'s name is ', dog2.getName())
  // console.log('dog1\'s colors is ', dog1.getColors()) // [ 'black', 'white', 'brown' ]
  // console.log('dog2\'s colors is ', dog2.getColors()) // [ 'black', 'white' ]

// 组合继承
  // 使用原型链继承原型上的属性和方法，通过盗用构造函数继承实例属性
  // 这样可以把方法定义在原型上实现重用，又可以让每个实例拥有自己的属性
  // 缺点
    // 调用两次父类的构造函数
// function Animal(name) {
//   this.name = name
//   this.colors = ['black', 'white']
// }
// Animal.prototype.getName = function () {
//   return this.name
// }
// function Dog(name, age) {
//   Animal.call(this, name)
//   this.age = age
// }
// Dog.prototype = new Animal()
// Dog.prototype.constructor = Dog
// let dog1 = new Dog('奶昔', 1)
// dog1.colors.push('brown')
// let dog2 = new Dog('豆沙', 2)
// console.log(dog2)

// 寄生组合继承
  // 优点
    // 不需要调用两次父类的构造函数
  // 代码有问题
  // function Animal (name) {
  //   this.name = name
  //   this.colors = ['black', 'white']
  // }
  // Animal.prototype.getName = function () {
  //   return this.name
  // }
  // function Dog(age) {
  //   this.age = age
  // }
  // function F () {}
  // F.prototype = Animal.prototype
  // let f = new F()
  // console.log('f', f.__proto__)
  // f.constructor = Dog
  // Dog.prototype = f
  // let dog1 = new Dog('奶昔', 1)

// class继承
class Animal {
  constructor (name) {
    this.name = name
  }
  getName () {
    return this.name
  }
}
class Dog extends Animal {
  constructor(name, age) {
    super(name)
    this.age = age
  }
}
let dog1 = new Dog('dog’s name', 20)
console.log(dog1.getName(), dog1.age)
